﻿#pragma once

#include <map>
#include <string_view>

template <typename T>
struct ValueGetter {};

template <>
struct ValueGetter<std::string_view> {
    template <typename P>
    static std::string_view GetParams(P& params, std::string_view key, std::string_view default_value) {
        auto it = params.find(key);
        if (it == params.end()) return default_value;
        return it->second;
    }
};

template <>
struct ValueGetter<std::string> {
    template <typename P>
    static std::string GetParams(P& params, std::string_view key, std::string default_value) {
        auto it = params.find(key);
        if (it == params.end()) return default_value;
        return it->second;
    }
};

template <>
struct ValueGetter<int> {
    template <typename P>
    static int GetParams(P& params, std::string_view key, int default_value) {
        auto it = params.find(key);
        if (it == params.end()) return default_value;
        return std::atoi(it->second.data());
    }
};

template <>
struct ValueGetter<bool> {
    template <typename P>
    static bool GetParams(P& params, std::string_view key, bool default_value) {
        auto it = params.find(key);
        if (it == params.end()) return default_value;
        return strcmp(it->second.c_str(), "true") == 0;
    }
};

class ParamsParser {
public:
    ParamsParser(int argc, char* argv[]) {
        for (int i = 1; i < argc; i++) {
            if (strncmp(argv[i], "--", 2) == 0) {
                char* p = strchr(argv[i] + 2, '=');
                if (p) {
                    std::string name(argv[i] + 2, p);
                    std::string val(p + 1);
                    params_[name] = val;
                }
            }
        }
    }

    template <typename T>
    T GetParams(std::string_view key, T default_value) {
        return ValueGetter<T>::GetParams(params_, key, default_value);
    }

private:
    std::map<std::string, std::string, std::less<>> params_;
};